using System;
using System.Collections.Generic;
using System.Text;
using FreeLancer.HRB.Domains;
using System.ComponentModel;

namespace FreeLancer.HRB.Core
{
  /// <summary>
  /// Represents a comment to a blog post.
  /// </summary>
  [Serializable]
  public sealed class Comment : IComparable<Comment>, IPublishable
  {
    #region Properties

    private PostComment _data;

    /// <summary>
    /// Data of comment.
    /// </summary>
    public PostComment Data
    {
      get { return _data; }
      set { _data = value; }
    }

    private IPublishable _post;

    /// <summary>
    /// Post
    /// </summary>
    public IPublishable Parent
    {
      get { return _post; }
      set { _post = value; }
    }

    #endregion

    #region Constructors

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="data">Post comment data</param>
    public Comment(PostComment data)
    {
      _data = data;
    }

    #endregion

    #region IPublishable Members

    /// <summary>
    /// Gets the title of the object
    /// </summary>
    /// <value></value>
    public string Title
    {
      get { return string.Empty; }// _data.Title; }
    }

    /// <summary>
    /// Gets or sets the content.
    /// </summary>
    /// <value>The content.</value>
    public string Content
    {
      get { return _data.Comment; }
    }

    /// <summary>
    /// Gets when the comment was created.
    /// </summary>
    public DateTime DateCreated
    {
      get { return _data.CommentDate; }
    }

    /// <summary>
    /// Gets when the comment was modified.
    /// </summary>
    public DateTime DateModified
    {
      get { return _data.CommentDate; }
    }

    /// <summary>
    /// The Id of the comment.
    /// </summary>
    public Guid Id
    {
      get { return _data.PostCommentId; }
    }

    /// <summary>
    /// Relative link
    /// </summary>
    public string RelativeLink
    {
      get { return Parent.RelativeLink.ToString() + "#id_" + Id; }
    }

    /// <summary>
    /// Absolute link
    /// </summary>
    public Uri AbsoluteLink
    {
      get { return new Uri(Parent.AbsoluteLink + "#id_" + Id); }
    }

    /// <summary>
    /// Gets the description. Returns always string.empty.
    /// </summary>
    /// <value>The description.</value>
    public string Description
    {
      get { return string.Empty; }
    }

    /// <summary>
    /// Gets or sets the author.
    /// </summary>
    /// <value>The author.</value>
    public string Author
    {
      get { return _data.Author; }
      set { _data.Author = value; }
    }

    /// <summary>
    /// Raises the Serving event
    /// </summary>
    public void OnServing(ServingEventArgs eventArgs)
    {
      if (Serving != null)
      {
        Serving(this, eventArgs);
      }
    }

    /// <summary>
    /// Not available.
    /// </summary>
    public List<Category> Categories
    {
      get { return null; }
    }

    /// <summary>
    /// Gets whether or not this comment has been published
    /// </summary>
    public bool IsPublished
    {
      get { return _data.IsApproved.Value; }
    }

    /// <summary>
    /// Gets whether or not this comment should be shown
    /// </summary>
    /// <value></value>
    public bool IsVisible
    {
      get { return _data.IsApproved.Value; }
    }

    #endregion

    #region Events

    /// <summary>
    /// Occurs when the post is being served to the output stream.
    /// </summary>
    public static event EventHandler<ServingEventArgs> Serving;
    /// <summary>
    /// Raises the event in a safe way
    /// </summary>
    public static void OnServing(Comment comment, ServingEventArgs arg)
    {
      if (Serving != null)
      {
        Serving(comment, arg);
      }
    }

    /// <summary>
    /// Occurs just before a comment is approved by the comment moderator.
    /// </summary>
    public static event EventHandler<CancelEventArgs> Approving;
    /// <summary>
    /// Raises the event in a safe way
    /// </summary>
    internal static void OnApproving(Comment comment, CancelEventArgs e)
    {
      if (Approving != null)
      {
        Approving(comment, e);
      }
    }

    /// <summary>
    /// Occurs after a comment is approved by the comment moderator.
    /// </summary>
    public static event EventHandler<EventArgs> Approved;
    /// <summary>
    /// Raises the event in a safe way
    /// </summary>
    internal static void OnApproved(Comment comment)
    {
      if (Approved != null)
      {
        Approved(comment, EventArgs.Empty);
      }
    }

    /// <summary>
    /// Occurs when the page is being attacked by robot spam.
    /// </summary>
    public static event EventHandler<EventArgs> SpamAttack;
    /// <summary>
    /// Raises the SpamAttack event in a safe way
    /// </summary>
    public static void OnSpamAttack()
    {
      if (SpamAttack != null)
      {
        SpamAttack(null, new EventArgs());
      }
    }

    #endregion

    #region IComparable<Comment> Members

    /// <summary>
    /// Compares the current object with another object of the same type.
    /// </summary>
    /// <param name="other">An object to compare with this object.</param>
    /// <returns>
    /// A 32-bit signed integer that indicates the relative order of the 
    /// objects being compared. The return value has the following meanings: 
    /// Value Meaning Less than zero This object is less than the other parameter.
    /// Zero This object is equal to other. Greater than zero This object is greater than other.
    /// </returns>
    public int CompareTo(Comment other)
    {
      return this.DateCreated.CompareTo(other.DateCreated);
    }

    #endregion
  }
}
